home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / wattcp / src / pcicmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  6.8 KB  |  297 lines

  1. #include"capalloc.h"
  2. #include"capstdio.h"
  3. #include <copyright.h>
  4. #include <wattcp.h>
  5. #include <mem.h>
  6.  
  7. /*
  8.  * ICMP - RFC 792
  9.  */
  10.  
  11. static char *unreach[] = {
  12.     "Network Unreachable",
  13.     "Host Unreachable",
  14.     "Protocol Unreachable",
  15.     "Port Unreachable",
  16.     "Fragmentation needed and DF set",
  17.     "Source Route Failed" };
  18. static char *exceed[] = {
  19.     "TTL exceeded in transit",
  20.     "Frag ReAsm time exceeded" };
  21.  
  22. static char *redirect[] = {
  23.     "Redirect for Network",
  24.     "Redirect for Host",
  25.     "Redirect for TOS and Network",
  26.     "Redirect for TOS and Host" };
  27.  
  28. /* constants */
  29.  
  30.  
  31. typedef struct icmp_unused {
  32.     byte     type;
  33.     byte    code;
  34.     word    checksum;
  35.     longword    unused;
  36.     in_Header    ip;
  37.     byte    spares[ 8 ];
  38. };
  39.  
  40. typedef struct icmp_pointer {
  41.     byte    type;
  42.     byte    code;
  43.     word    checksum;
  44.     byte    pointer;
  45.     byte    unused[ 3 ];
  46.     in_Header    ip;
  47. };
  48. typedef struct icmp_ip {
  49.     byte    type;
  50.     byte    code;
  51.     word    checksum;
  52.     longword    ipaddr;
  53.     in_Header    ip;
  54. };
  55. typedef struct icmp_echo {
  56.     byte    type;
  57.     byte    code;
  58.     word    checksum;
  59.     word    identifier;
  60.     word    sequence;
  61. };
  62.  
  63. typedef struct icmp_timestamp {
  64.     byte    type;
  65.     byte    code;
  66.     word    checksum;
  67.     word    identifier;
  68.     word    sequence;
  69.     longword    original;    /* original timestamp */
  70.     longword    receive;    /* receive timestamp */
  71.     longword    transmit;    /* transmit timestamp */
  72. };
  73.  
  74. typedef struct icmp_info {
  75.     byte    type;
  76.     byte    code;
  77.     word    checksum;
  78.     word    identifier;
  79.     word    sequence;
  80. };
  81.  
  82. typedef union  {
  83.     struct icmp_unused    unused;
  84.     struct icmp_pointer    pointer;
  85.     struct icmp_ip        ip;
  86.     struct icmp_echo    echo;
  87.     struct icmp_timestamp    timestamp;
  88.     struct icmp_info    info;
  89. } icmp_pkt;
  90.  
  91. typedef struct _pkt {
  92.     in_Header     in;
  93.     icmp_pkt     icmp;
  94.     in_Header    data;
  95. };
  96.  
  97. static word icmp_id = 0;
  98.  
  99. static longword ping_hcache = 0;    /* host */
  100. static longword ping_tcache = 0;    /* time */
  101. static longword ping_number = 0;
  102.  
  103. longword _chk_ping( longword host, longword *ptr )
  104. {
  105.     if ( ping_hcache == host ) {
  106.     ping_hcache = 0xffffffffL;
  107.     *ptr = ping_number;
  108.     return( ping_tcache );
  109.     }
  110.     return( 0xffffffffL );
  111. }
  112.  
  113.  
  114. void icmp_print( icmp_pkt *icmp, char *msg)
  115. {
  116.     outs("\nICMP: ");
  117.     outs( msg );
  118.     outs("\n");
  119. }
  120.  
  121. /*
  122.  *
  123.  */
  124. struct _pkt *icmp_Format( longword destip )
  125. {
  126.     eth_address dest;
  127.     char *temp;
  128.  
  129.     /* we use arp rather than supplied hardware address */
  130.     /* after first ping this will still be in cache */
  131.  
  132.     if ( !_arp_resolve( destip , &dest, 0 ))
  133.     return( NULL );                /* unable to find address */
  134.     return( (struct _pkt*)_eth_formatpacket( &dest, 8 ));
  135. }
  136. /*
  137.  * icmp_Reply - format a reply packet
  138.  *            - note that src and dest are NETWORK order not host!!!!
  139.  */
  140. void *icmp_Reply( struct _pkt *p, longword src, longword dest, int icmp_length )
  141. {
  142.     in_Header *ip;
  143.     icmp_pkt *icmp;
  144.  
  145.     ip = &p->in;
  146.     memset( ip, 0, sizeof( in_Header ));
  147.     icmp = &p->icmp;
  148.  
  149.     /* finish the icmp checksum portion */
  150.     icmp->unused.checksum = 0;
  151.     icmp->unused.checksum = ~checksum( icmp, icmp_length );
  152.  
  153.     /* encapsulate into a nice ip packet */
  154.     ip->ver = 4;
  155.     ip->hdrlen = 5;
  156.     ip->length = intel16( sizeof( in_Header ) + icmp_length);
  157.     ip->tos = 0;
  158.     ip->identification = intel16( icmp_id ++);    /* not using ip id */
  159. //    ip->frag = 0;
  160.     ip->ttl = 250;
  161.     ip->proto = ICMP_PROTO;
  162.     ip->checksum = 0;
  163.     ip->source = src;
  164.     ip->destination = dest;
  165.     ip->checksum = ~ checksum( ip, sizeof( in_Header ));
  166.  
  167.     _eth_send( intel16( ip->length ));
  168.  
  169. }
  170.  
  171. icmp_handler( in_Header *ip )
  172. {
  173.     icmp_pkt *icmp, *newicmp;
  174.     struct _pkt *pkt;
  175.     int len, code;
  176.     in_Header *ret;
  177.  
  178.     len = in_GetHdrlenBytes( ip );
  179.     icmp = (icmp_pkt*)((byte *)ip + len);
  180.     len = intel16( ip->length ) - len;
  181.     if ( checksum( icmp, len ) != 0xffff ) {
  182.     outs("ICMP received with bad checksum\n");
  183.     return( 1 );
  184.     }
  185.  
  186.     code = icmp->unused.code;
  187.     ret = & (icmp->ip.ip);
  188.  
  189.     switch ( icmp->unused.type) {
  190.     case 0 : /* icmp echo reply received */
  191.         /* icmp_print( icmp, "received icmp echo receipt"); */
  192.  
  193.         /* check if we were waiting for it */
  194.         ping_hcache = intel( ip->source );
  195.         ping_tcache = set_timeout( 1 ) - *(longword *)(&icmp->echo.identifier );
  196.         if (ping_tcache > 0xffffffffL)
  197.             ping_tcache += 0x1800b0L;
  198.         ping_number = *(longword*)( ((byte*)(&icmp->echo.identifier)) + 4 );
  199.         /* do more */
  200.         break;
  201.  
  202.     case 3 : /* destination unreachable message */
  203.         if (code < 6) {
  204.             icmp_print( icmp, unreach[ code ]);
  205.  
  206.             /* handle udp or tcp socket */
  207.             if (ret->proto == TCP_PROTO)
  208.                         _tcp_cancel( ret, 1, unreach[ code ], 0 );
  209.             if (ret->proto == UDP_PROTO)
  210.             _udp_cancel( ret );
  211.         }
  212.         break;
  213.  
  214.     case 4  : /* source quench */
  215. #ifndef RELEASE
  216.         if (debug_on > 0 ) icmp_print( icmp, "Source Quench");
  217. #endif /* RELEASE */
  218.                 if (ret->proto == TCP_PROTO)
  219.                     _tcp_cancel( ret, 2, NULL, 0 );
  220.         break;
  221.  
  222.     case 5  : /* redirect */
  223.         if (code < 4) {
  224.                     if (ret->proto == TCP_PROTO)
  225.                         /* do it to some socket guy */
  226.                         _tcp_cancel( ret, 5, NULL, icmp->ip.ipaddr );
  227.  
  228. #ifndef RELEASE
  229.             if (debug_on > 0 ) icmp_print( icmp, redirect[ code ]);
  230. #endif /* RELEASE */
  231.         }
  232.         break;
  233.  
  234.     case 8  : /* icmp echo request */
  235.         /* icmp_print( icmp, "PING requested of us"); */
  236.  
  237.         /* do arp and create packet */
  238. #ifdef OLD
  239.         if (!(pkt = icmp_Format( intel( ip->source ))))
  240.             break;
  241. #else
  242.         /* format the packet with the request's hardware address */
  243.         pkt = (struct _pkt*)(_eth_formatpacket( _eth_hardware(ip), 8));
  244. #endif OLD
  245.         newicmp = &pkt->icmp;
  246.  
  247. /* newicmp = (icmp_pkt*)((byte *)(pkt) + sizeof(in_Header)); */
  248.  
  249.         movmem( icmp, newicmp, len );
  250.         newicmp->echo.type = 0;
  251.         newicmp->echo.code = code;
  252.  
  253.         /* use supplied ip values in case we ever multi-home */
  254.         /* note that ip values are still in network order */
  255.         icmp_Reply( pkt,ip->destination, ip->source, len );
  256.  
  257.         /* icmp_print( newicmp, "PING reply sent"); */
  258.  
  259.         break;
  260.  
  261.     case 11 : /* time exceeded message */
  262.         if (code < 2 ) {
  263.             icmp_print( icmp, exceed[ code ]);
  264.                     if ((ret->proto == TCP_PROTO) && (code != 1))
  265.                         _tcp_cancel( ret, 1, NULL, 0 );
  266.                 }
  267.         break;
  268.  
  269.     case 12 : /* parameter problem message */
  270.         icmp_print( icmp, "IP Parameter problem");
  271.         break;
  272.  
  273.     case 13 : /* timestamp message */
  274.         icmp_print( icmp, "Timestamp message");
  275.         /* send reply */
  276.         break;
  277.  
  278.     case 14 : /* timestamp reply */
  279.         icmp_print( icmp, "Timestamp reply");
  280.         /* should store */
  281.         break;
  282.  
  283.     case 15 : /* info request */
  284.         icmp_print( icmp,"Info requested");
  285.         /* send reply */
  286.         break;
  287.  
  288.     case 16 : /* info reply */
  289.         icmp_print( icmp,"Info reply");
  290.         break;
  291.  
  292.     }
  293.     return( 1 );
  294. }
  295.  
  296.  
  297.